package com.qijian.flowable.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qijian.common.annotation.Log;
import com.qijian.common.enums.BusinessType;
import com.qijian.common.utils.*;
import com.qijian.common.utils.mybatis.WhereEntityTool;
import com.qijian.flowable.common.BaseFlowableController;
import com.qijian.flowable.common.FlowablePage;
import com.qijian.flowable.common.Result;
import com.qijian.flowable.common.model.FlowTaskModel;
import com.qijian.flowable.constant.FlowableConstant;
import com.qijian.flowable.domain.FlowableRecord;
import com.qijian.flowable.domain.query.FlowableRecordQuery;
import com.qijian.flowable.domain.query.TaskQueryVo;
import com.qijian.flowable.domain.vo.*;
import com.qijian.flowable.service.IFlowableRecordService;
import com.qijian.flowable.service.IFlowableTaskService;
import com.qijian.flowable.util.FlowableUtils;
import com.qijian.flowable.wapper.TaskListWrapper;
import com.qijian.flowable.wapper.TaskTodoListWrapper;
import com.qijian.tool.domain.Msg;
import com.qijian.tool.service.IMsgService;
import com.qijian.tool.utils.ManualPageUtils;
import lombok.RequiredArgsConstructor;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryProperty;
import org.flowable.task.service.impl.TaskQueryProperty;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 庄金明
 * @date 2020年3月23日
 */
@RequiredArgsConstructor
@RestController
@RequestMapping("/flowable/task")
public class TaskController extends BaseFlowableController {
    private final IFlowableTaskService flowableTaskService;

    private final IFlowableRecordService flowableRecordService;

    private final IMsgService msgService;

    private static final Map<String, QueryProperty> allowedSortProperties = new HashMap<>();
    private static final Map<String, QueryProperty> allowedSortPropertiesTodo = new HashMap<>();

    static {
        allowedSortProperties.put("deleteReason", HistoricTaskInstanceQueryProperty.DELETE_REASON);
        allowedSortProperties.put("duration", HistoricTaskInstanceQueryProperty.DURATION);
        allowedSortProperties.put("endTime", HistoricTaskInstanceQueryProperty.END);
        allowedSortProperties.put(FlowableConstant.EXECUTION_ID, HistoricTaskInstanceQueryProperty.EXECUTION_ID);
        allowedSortProperties.put("taskInstanceId", HistoricTaskInstanceQueryProperty.HISTORIC_TASK_INSTANCE_ID);
        allowedSortProperties.put(FlowableConstant.PROCESS_DEFINITION_ID,
                HistoricTaskInstanceQueryProperty.PROCESS_DEFINITION_ID);
        allowedSortProperties.put(FlowableConstant.PROCESS_INSTANCE_ID,
                HistoricTaskInstanceQueryProperty.PROCESS_INSTANCE_ID);
        allowedSortProperties.put("assignee", HistoricTaskInstanceQueryProperty.TASK_ASSIGNEE);
        allowedSortProperties.put(FlowableConstant.TASK_DEFINITION_KEY,
                HistoricTaskInstanceQueryProperty.TASK_DEFINITION_KEY);
        allowedSortProperties.put("description", HistoricTaskInstanceQueryProperty.TASK_DESCRIPTION);
        allowedSortProperties.put("dueDate", HistoricTaskInstanceQueryProperty.TASK_DUE_DATE);
        allowedSortProperties.put(FlowableConstant.NAME, HistoricTaskInstanceQueryProperty.TASK_NAME);
        allowedSortProperties.put("owner", HistoricTaskInstanceQueryProperty.TASK_OWNER);
        allowedSortProperties.put("priority", HistoricTaskInstanceQueryProperty.TASK_PRIORITY);
        allowedSortProperties.put(FlowableConstant.TENANT_ID, HistoricTaskInstanceQueryProperty.TENANT_ID_);
        allowedSortProperties.put("startTime", HistoricTaskInstanceQueryProperty.START);

        allowedSortPropertiesTodo.put(FlowableConstant.PROCESS_DEFINITION_ID, TaskQueryProperty.PROCESS_DEFINITION_ID);
        allowedSortPropertiesTodo.put(FlowableConstant.PROCESS_INSTANCE_ID, TaskQueryProperty.PROCESS_INSTANCE_ID);
        allowedSortPropertiesTodo.put(FlowableConstant.TASK_DEFINITION_KEY, TaskQueryProperty.TASK_DEFINITION_KEY);
        allowedSortPropertiesTodo.put("dueDate", TaskQueryProperty.DUE_DATE);
        allowedSortPropertiesTodo.put(FlowableConstant.NAME, TaskQueryProperty.NAME);
        allowedSortPropertiesTodo.put("priority", TaskQueryProperty.PRIORITY);
        allowedSortPropertiesTodo.put(FlowableConstant.TENANT_ID, TaskQueryProperty.TENANT_ID);
        allowedSortPropertiesTodo.put("createTime", TaskQueryProperty.CREATE_TIME);
    }

    protected HistoricTaskInstanceQuery createHistoricTaskInstanceQuery(TaskQueryVo taskQueryVo) {
        HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery();
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskId())) {
            query.taskId(taskQueryVo.getTaskId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessInstanceId())) {
            query.processInstanceId(taskQueryVo.getProcessInstanceId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessInstanceBusinessKey())) {
            query.processInstanceBusinessKeyLike(ObjectUtils.convertToLike(taskQueryVo.getProcessInstanceBusinessKey()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionKey())) {
            query.processDefinitionKeyLike(ObjectUtils.convertToLike(taskQueryVo.getProcessDefinitionKey()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionId())) {
            query.processDefinitionId(taskQueryVo.getProcessDefinitionId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionName())) {
            query.processDefinitionNameLike(ObjectUtils.convertToLike(taskQueryVo.getProcessDefinitionName()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getExecutionId())) {
            query.executionId(taskQueryVo.getExecutionId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskName())) {
            query.taskNameLike(ObjectUtils.convertToLike(taskQueryVo.getTaskName()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDescription())) {
            query.taskDescriptionLike(ObjectUtils.convertToLike(taskQueryVo.getTaskDescription()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDefinitionKey())) {
            query.taskDefinitionKeyLike(ObjectUtils.convertToLike(taskQueryVo.getTaskDefinitionKey()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskAssignee())) {
            query.taskAssignee(taskQueryVo.getTaskAssignee());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskOwner())) {
            query.taskOwner(taskQueryVo.getTaskOwner());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskInvolvedUser())) {
            query.taskInvolvedUser(taskQueryVo.getTaskInvolvedUser());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskPriority())) {
            query.taskPriority(taskQueryVo.getTaskPriority());
        }
        Boolean finished = CommonUtil.isEmptyDefault(taskQueryVo.getFinished(), false);
        Boolean unfinished = CommonUtil.isEmptyDefault(taskQueryVo.getUnfinished(), false);
        if (!finished.equals(unfinished)) {
            if (finished) {
                query.finished();
            }
            if (unfinished) {
                query.unfinished();
            }
        }
        Boolean processFinished = CommonUtil.isEmptyDefault(taskQueryVo.getProcessFinished(), false);
        Boolean processUnfinished = CommonUtil.isEmptyDefault(taskQueryVo.getProcessUnfinished(), false);
        if (!processFinished.equals(processUnfinished)) {
            if (processFinished) {
                query.processFinished();
            }
            if (processUnfinished) {
                query.processUnfinished();
            }
        }

        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskParentTaskId())) {
            query.taskParentTaskId(taskQueryVo.getTaskParentTaskId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTenantId())) {
            query.taskTenantId(taskQueryVo.getTenantId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCandidateUser())) {
            query.taskCandidateUser(taskQueryVo.getTaskCandidateUser());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCandidateGroup())) {
            query.taskCandidateGroup(taskQueryVo.getTaskCandidateGroup());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCandidateGroupIn())) {
            query.taskCandidateGroupIn(Arrays.asList(taskQueryVo.getTaskCandidateGroupIn().split(",")));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDueAfter())) {
            query.taskDueAfter(ObjectUtils.convertToDate(taskQueryVo.getTaskDueAfter()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDueBefore())) {
            query.taskDueBefore(ObjectUtils.convertToDate(taskQueryVo.getTaskDueBefore()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCreatedAfter())) {
            query.taskCreatedAfter(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCreatedAfter()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCreatedBefore())) {
            query.taskCreatedBefore(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCreatedBefore()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCompletedAfter())) {
            query.taskCompletedAfter(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCompletedAfter()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCompletedBefore())) {
            query.taskCompletedBefore(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCompletedBefore()));
        }

        return query;
    }

    protected TaskQuery createTaskQuery(TaskQueryVo taskQueryVo) {
        TaskQuery query = taskService.createTaskQuery();
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessInstanceId())) {
            query.processInstanceId(taskQueryVo.getProcessInstanceId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskName())) {
            query.taskNameLike(ObjectUtils.convertToLike(taskQueryVo.getTaskName()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessInstanceBusinessKey())) {
            query.processInstanceBusinessKeyLike(ObjectUtils.convertToLike(taskQueryVo.getProcessInstanceBusinessKey()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessInstanceId())) {
            query.processInstanceId(taskQueryVo.getProcessInstanceId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionKey())) {
            query.processDefinitionKeyLike(ObjectUtils.convertToLike(taskQueryVo.getProcessDefinitionKey()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionId())) {
            query.processDefinitionId(taskQueryVo.getProcessDefinitionId());
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getProcessDefinitionName())) {
            query.processDefinitionNameLike(ObjectUtils.convertToLike(taskQueryVo.getProcessDefinitionName()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDueAfter())) {
            query.taskDueAfter(ObjectUtils.convertToDate(taskQueryVo.getTaskDueAfter()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskDueBefore())) {
            query.taskDueBefore(ObjectUtils.convertToDate(taskQueryVo.getTaskDueBefore()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCreatedAfter())) {
            query.taskCreatedAfter(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCreatedAfter()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTaskCreatedBefore())) {
            query.taskCreatedBefore(ObjectUtils.convertToDatetime(taskQueryVo.getTaskCreatedBefore()));
        }
        if (ObjectUtils.isNotEmpty(taskQueryVo.getTenantId())) {
            query.taskTenantId(taskQueryVo.getTenantId());
        }
        if (taskQueryVo.getZt() != null && taskQueryVo.getZt()){
            query.taskCreatedBefore(DateUtils.addDays(DateUtils.getNowDate(),-2));
        }
        Boolean suspended = CommonUtil.isEmptyDefault(taskQueryVo.getSuspended(), false);
        Boolean active = CommonUtil.isEmptyDefault(taskQueryVo.getActive(), false);
        if (!suspended.equals(active)) {
            if (suspended) {
                query.suspended();
            }
            if (active) {
                query.active();
            }
        }
        return query;
    }

    @PreAuthorize("@ss.hasPermi('flowable:task:list')")
    @GetMapping
    public Result list(TaskQueryVo taskQueryVo) {
        HistoricTaskInstanceQuery query = createHistoricTaskInstanceQuery(taskQueryVo);
        FlowablePage page = this.pageList(taskQueryVo, query, TaskListWrapper.class, allowedSortProperties,
                HistoricTaskInstanceQueryProperty.START);
        return Result.ok(page);
    }

    @GetMapping(value = "/listDone")
    public Result listDone(TaskQueryVo taskQueryVo) {
        HistoricTaskInstanceQuery query = createHistoricTaskInstanceQuery(taskQueryVo);
        query.finished().or().taskAssignee(SecurityUtils.getUserId().toString()).taskOwner(SecurityUtils.getUserId().toString()).endOr();
        FlowablePage page = this.pageList(taskQueryVo, query, TaskListWrapper.class, allowedSortProperties,
                HistoricTaskInstanceQueryProperty.START);
        return Result.ok(page);
    }

    @GetMapping(value = "/listTodo")
    public Result listTodo(TaskQueryVo taskQueryVo) {
        Long size = Long.valueOf(taskQueryVo.getSize());
        Long current = Long.valueOf(taskQueryVo.getCurrent());
        taskQueryVo.setSize(100);
        taskQueryVo.setCurrent(1);
        FlowablePage page = new FlowablePage();
        List<String> processInstanceIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(taskQueryVo.getProcessInstanceName()) || StringUtils.isNotEmpty(taskQueryVo.getProjectNos())) {
            FlowableRecordQuery flowablerecordquery = new FlowableRecordQuery();
            if (StringUtils.isNotEmpty(taskQueryVo.getProjectNos())) {
                flowablerecordquery.setProjectNos(taskQueryVo.getProjectNos());
            }
            if (StringUtils.isNotEmpty(taskQueryVo.getProcessInstanceName())) {
                flowablerecordquery.setRecordName(taskQueryVo.getProcessInstanceName());
            }
            List<FlowableRecord> list = flowableRecordService.list(WhereEntityTool.invoke(flowablerecordquery, false));
            if (CollectionUtil.isEmpty(list)) {
                return Result.ok(page);
            }
            processInstanceIds = list.stream().map(e -> e.getProcessInstanceId()).collect(Collectors.toList());
        }
        String userId = SecurityUtils.getUserId().toString();
        TaskQuery query = createTaskQuery(taskQueryVo);
        query.taskCategory(FlowableConstant.CATEGORY_TODO);
        if (CollectionUtil.isNotEmpty(processInstanceIds)) {
            query.processInstanceIdIn(processInstanceIds);
        }
        query.or().taskCandidateOrAssigned(userId).taskOwner(userId).endOr();
        page = this.pageList(taskQueryVo, query, TaskTodoListWrapper.class, allowedSortProperties,
                TaskQueryProperty.CREATE_TIME);

        // 合并转发任务消息
        List<Msg> zf0 = msgService.list(new LambdaQueryWrapper<Msg>().eq(Msg::getRemark, "ZF_0").eq(Msg::getUserId, userId));


        List<FlowTaskModel> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {

            List<String> processInstanceIdList = new ArrayList<>();
            page.getRecords().stream().forEach(e -> {
                FlowTaskModel flowTaskModel = JSONUtil.toBean(JSON.toJSONString(e), FlowTaskModel.class);
                processInstanceIdList.add(flowTaskModel.getProcessInstanceId());
                list.add(flowTaskModel);
            });
            List<FlowableRecord> flowableRecords = flowableRecordService.list(new LambdaQueryWrapper<FlowableRecord>().in(FlowableRecord::getProcessInstanceId, processInstanceIdList));
            if (CollectionUtil.isNotEmpty(flowableRecords)) {
                list.stream().forEach(e -> {
                    flowableRecords.stream().filter(n -> n.getProcessInstanceId().equals(e.getProcessInstanceId())).findFirst().ifPresent(m -> {
                        JSONObject jsonObject = JSON.parseObject(m.getBusinessValues());
                        if (jsonObject != null) {
                            e.setDeptName(jsonObject.get("deptName") == null ? null : jsonObject.get("deptName").toString());
                            e.setNickName(jsonObject.get("userName") == null ? null : jsonObject.get("userName").toString());
                            e.setItemName(jsonObject.get("itemName") == null ? null : jsonObject.get("itemName").toString());
                            e.setProjectNos(m.getProjectNos());
                        }
                    });
                });

            }

        }
        if (CollectionUtil.isNotEmpty(zf0)) {
            List<String> processInstanceIdList1 = new ArrayList<>();
            zf0.stream().forEach(e -> {
                FlowTaskModel flowTaskModel = new FlowTaskModel();
                flowTaskModel.setCategory(FlowableConstant.CATEGORY_TODO);
                flowTaskModel.setAssignee(e.getUserId().toString());
                flowTaskModel.setName(StringUtils.isNotEmpty(e.getMsgLevel()) ? e.getMsgLevel() : "" + "_转发");
                flowTaskModel.setPriority(50);
                flowTaskModel.setProcessInstanceId(e.getProcessInstanceId());
                flowTaskModel.setProcessInstanceName(e.getTitle());
                flowTaskModel.setCreateTime(e.getCreateTime());
                flowTaskModel.setId(e.getTaskId());
                processInstanceIdList1.add(flowTaskModel.getProcessInstanceId());
                list.add(flowTaskModel);
            });
            List<FlowableRecord> flowableRecords = flowableRecordService.list(new LambdaQueryWrapper<FlowableRecord>().in(FlowableRecord::getProcessInstanceId, processInstanceIdList1));
            if (CollectionUtil.isNotEmpty(flowableRecords)) {
                list.stream().forEach(e -> {
                    flowableRecords.stream().filter(n -> n.getProcessInstanceId().equals(e.getProcessInstanceId())).findFirst().ifPresent(m -> {
                        JSONObject jsonObject = JSON.parseObject(m.getBusinessValues());
                        if (jsonObject != null) {
                            e.setDeptName(jsonObject.get("deptName") == null ? null : jsonObject.get("deptName").toString());
                            e.setNickName(jsonObject.get("userName") == null ? null : jsonObject.get("userName").toString());
                            e.setItemName(jsonObject.get("itemName") == null ? null : jsonObject.get("itemName").toString());
                            e.setProjectNos(m.getProjectNos());
                        }
                    });
                });

            }
            list.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        }
        //手动分页
        Page page1 = ManualPageUtils.setPage(list, current, size);
        page.setRecords(page1.getRecords());
        return Result.ok(page);
    }

    @GetMapping(value = "/listToRead")
    public Result listToRead(TaskQueryVo taskQueryVo) {
        String userId = SecurityUtils.getUserId().toString();
        TaskQuery query = createTaskQuery(taskQueryVo);
        query.taskCategory(FlowableConstant.CATEGORY_TO_READ);
        query.or().taskAssignee(userId).taskOwner(userId).endOr();
        FlowablePage page = this.pageList(taskQueryVo, query, TaskTodoListWrapper.class, allowedSortProperties,
                TaskQueryProperty.CREATE_TIME);
        return Result.ok(page);
    }

    @GetMapping(value = "/queryById")
    public Result queryById(@RequestParam String taskId) {
        TaskResponse task = flowableTaskService.getTask(taskId);
        return Result.ok(task);
    }

    @Log(title = "修改任务", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('flowable:task:update')")
    @PutMapping(value = "/update")
    public Result update(@RequestBody TaskUpdateVo taskUpdateRequest) {
        TaskResponse task = flowableTaskService.updateTask(taskUpdateRequest);
        return Result.ok(task);
    }

    @Log(title = "删除任务", businessType = BusinessType.DELETE)
    @PreAuthorize("@ss.hasPermi('flowable:task:delete')")
    @DeleteMapping(value = "/delete")
    public Result delete(@RequestParam String taskId) {
        flowableTaskService.deleteTask(taskId);
        return Result.ok();
    }

    @Log(title = "转办任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/assign")
    public Result assign(@RequestBody TaskVo taskRequest) {
        flowableTaskService.assignTask(taskRequest);
        return Result.ok();
    }



    @Log(title = "委派任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/delegate")
    public Result delegate(@RequestBody TaskVo taskRequest) {
        flowableTaskService.delegateTask(taskRequest);
        return Result.ok();
    }



    @Log(title = "认领任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/claim")
//    @RedissonLock(lockIndexs = 0, fieldNames = "taskId")
    public Result claim(@RequestBody TaskVo taskRequest) {
        flowableTaskService.claimTask(taskRequest);
        return Result.ok();
    }

    @Log(title = "取消认领任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/unclaim")
    public Result unclaim(@RequestBody TaskVo taskRequest) {
        flowableTaskService.unclaimTask(taskRequest);
        return Result.ok();
    }

    @Log(title = "催办", businessType = BusinessType.OTHER)
    @PutMapping(value = "/urging")
    public ResponseEntity<Object> urging(@RequestBody TaskVo taskRequest) {
        flowableTaskService.urging(taskRequest);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log(title = "完成任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/complete")
    public Result complete(@RequestBody TaskVo taskRequest) {
        flowableTaskService.completeTask(taskRequest, SecurityUtils.getUserId().toString());
        return Result.ok();
    }

    @Log(title = "结束流程实例", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/stopProcessInstance")
    public Result stopProcessInstance(@RequestBody TaskVo taskRequest) {
        flowableTaskService.stopProcessInstance(taskRequest);
        return Result.ok();
    }

    @GetMapping(value = "/renderedTaskForm")
    public Result renderedTaskForm(@RequestParam String taskId) {
        permissionService.validateReadPermissionOnTask2(taskId, SecurityUtils.getUserId().toString(), true, true);
        Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
        return Result.ok(renderedTaskForm);
    }

    @GetMapping(value = "/executeTaskData")
    public Result executeTaskData(@RequestParam String taskId) {
        Task task = permissionService.validateReadPermissionOnTask2(taskId, SecurityUtils.getUserId().toString(), true, true);

        Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        UserTask userTask = (UserTask) process.getFlowElement(task.getTaskDefinitionKey(), true);
        if (userTask == null) {
            throw new FlowableObjectNotFoundException("Can not find userTask by id " + task.getTaskDefinitionKey());
        }

        String startFormKey = formService.getStartFormKey(task.getProcessDefinitionId());
        String taskFormKey = formService.getTaskFormKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
        Object renderedStartForm = formService.getRenderedStartForm(task.getProcessDefinitionId());
        Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
        Map<String, Object> variables = runtimeService.getVariables(task.getProcessInstanceId());

        ProcessInstance processInstance =
                runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        Boolean showBusinessKey = isShowBusinessKey(task.getProcessDefinitionId());

        ExecuteTaskDataVo executeTaskDataVo = new ExecuteTaskDataVo();
        executeTaskDataVo.setStartUserId(processInstance.getStartUserId());
        executeTaskDataVo.setStartFormKey(startFormKey);
        executeTaskDataVo.setTaskFormKey(taskFormKey);
        executeTaskDataVo.setRenderedStartForm(renderedStartForm);
        executeTaskDataVo.setRenderedTaskForm(renderedTaskForm);
        executeTaskDataVo.setVariables(variables);
        executeTaskDataVo.setShowBusinessKey(showBusinessKey);
        // 当前任务是发起者
        if (FlowableConstant.INITIATOR.equals(task.getTaskDefinitionKey())) {
            executeTaskDataVo.setInitiator(true);
        }

        String buttons = FlowableUtils.getFlowableAttributeValue(userTask, FlowableConstant.BUTTONS);
        if (buttons != null) {
            executeTaskDataVo.setButtons(buttons.split(","));
        }

        historyService.createHistoricVariableInstanceQuery().processInstanceId("ss").variableNameLike("ss");
        return Result.ok(executeTaskDataVo);
    }

    @GetMapping(value = "/backNodes")
    public Result backNodes(@RequestParam String taskId) {
        List<FlowNodeResponse> datas = flowableTaskService.getBackNodes(taskId);
        return Result.ok(datas);
    }

    @Log(title = "退回任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/back")
    public Result back(@RequestBody TaskVo taskRequest) {
        taskRequest.setCurrentId(SecurityUtils.getUserId().toString());
        flowableTaskService.backTask(taskRequest);
        return Result.ok();
    }



    @Log(title = "阅读任务", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/read")
    public Result read(@RequestBody TaskVo taskRequest) {
        flowableTaskService.readTask(taskRequest);
        return Result.ok();
    }

    @PutMapping(value = "/doSomething")
    public void doSomething(String processInstanceId) {
        // 获取历史流程实例
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId("")
                .singleResult();

        if (historicProcessInstance != null) {
            // 获取历史活动实例，这些是流程中的每个步骤
            List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .orderByHistoricActivityInstanceId()
                    .asc()
                    .list();

            // 从最后一个活动实例开始撤回
            for (int i = historicActivityInstances.size() - 1; i >= 0; i--) {
                HistoricActivityInstance activityInstance = historicActivityInstances.get(i);

                // 判断是否可以撤回
                if (activityInstance.getActivityType() != "startEvent") {
                    // 撤回流程到指定的历史活动实例
                    deleteHistoricActivityInstancesBetween(activityInstance.getId(), historicProcessInstance.getEndTime());
                }
            }
        }
    }

    public void deleteHistoricActivityInstancesBetween(String activityInstanceId, Date activityInstanceEndTime) {


    }


}
